#include <jni.h>
#include <string>
#include <setjmp.h>
#include <android/bitmap.h>
#include <android/log.h>
#include "libjpeg/jpeglib.h"
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <android/bitmap.h>
#include <stdio.h>

#define TAG "NativeJPEG"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
#define UNSUPPORT_BITMAP_FORMAT -99
#define FAILED_OPEN_OUTPATH -100
#define SUCCESS_COMPRESS 1


typedef uint8_t BYTE;

// 自定义error结构体
struct my_error_mgr {
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};

extern "C" JNIEXPORT jstring JNICALL
Java_com_huitao_jpegdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}


const char *jstringToString(JNIEnv *env, jstring jstr) {
    char *ret;
    const char *c_str = env->GetStringUTFChars(jstr, NULL);
    jsize len = env->GetStringLength(jstr);
    if (c_str != NULL) {
        ret = (char *) malloc(len + 1);
        memcpy(ret, c_str, len);
        ret[len] = 0;
    }
    env->ReleaseStringUTFChars(jstr, c_str);
    return ret;
}

int compressJPEG(BYTE *data, int width, int height, jint quality, const char *path) {
    int nComponent = 3;
    FILE *f = fopen(path, "wb");
    if (f == NULL) {
        return FAILED_OPEN_OUTPATH;
    }

    // 初始化JPEG对象，为其分配空间
    struct my_error_mgr my_err{};
    struct jpeg_compress_struct jcs{};
    jcs.err = jpeg_std_error(&my_err.pub);
    if (setjmp(my_err.setjmp_buffer)) {
        return 0;
    }
    jpeg_create_compress(&jcs);

    // 指定压缩数据源，设定压缩参数
    // 使用哈夫曼算法压缩编码
    jpeg_stdio_dest(&jcs, f);
    jcs.image_width = width;
    jcs.image_height = height;
    jcs.arith_code = false; // false->哈夫曼编码
    jcs.input_components = nComponent;
    jcs.in_color_space = JCS_RGB;
    jpeg_set_defaults(&jcs);
    jcs.optimize_coding = quality;  // 压缩质量 0~100
    jpeg_set_quality(&jcs, quality, true);
    // 开始压缩，一行一行处理
    jpeg_start_compress(&jcs, true);
    JSAMPROW row_point[1];
    int row_stride;
    row_stride = jcs.image_width * nComponent;
    while (jcs.next_scanline < jcs.image_height) {
        row_point[0] = &data[jcs.next_scanline * row_stride];
        jpeg_write_scanlines(&jcs, row_point, 1);
    }
    // 结束压缩，释放资源
    if (jcs.optimize_coding != 0) {
        LOGI("使用哈夫曼压缩编码完成");
    }
    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);
    fclose(f);
    return SUCCESS_COMPRESS;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_huitao_jpegdemo_MainActivity_nativeCompressJPEG(JNIEnv *env, jobject thiz, jobject bitmap,
                                                         jint quality, jstring out_path) {
// 获取bitmap的属性信息
    int ret;
    int width, height, format;
    int color;
    BYTE r, g, b;
    BYTE *pixelsColor;
    BYTE *data, *tmpData;
    AndroidBitmapInfo androidBitmapInfo;
    const char *outPath = jstringToString(env, out_path);
    LOGI("outPath=%s", outPath);
    if ((ret = AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo)) < 0) {
        LOGI("AndroidBitmap_getInfo failed, error=%d", ret);
        return ret;
    }
    if ((ret = AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void **>(&pixelsColor))) <
        0) {
        LOGI("AndroidBitmap_lockPixels failed, error=%d", ret);
        return ret;
    }
    width = androidBitmapInfo.width;
    height = androidBitmapInfo.height;
    format = androidBitmapInfo.format;
    LOGI("open image:w=%d, h=%d, format=%d", width, height, format);
    // 将bitmap转换为rgb数据,只处理RGBA_8888格式
    // 一行一行的处理，每个像素占4个字节，包括a、r、g、b三个分量，每个分量占8位
    data = (BYTE *) malloc(width * height * 3);
    tmpData = data;
    for (int i = 0; i < height; ++i) {
        for (int j = 0; j < width; ++j) {
            if (format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
                color = *((int *) pixelsColor);
                b = (color >> 16) & 0xFF;
                g = (color >> 8) & 0xFF;
                r = (color >> 0) & 0xFF;
                *data = r;
                *(data + 1) = g;
                *(data + 2) = b;
                data += 3;
                // 处理下一个像素，在内存中即占4个字节
                pixelsColor += 4;
            } else {
                return UNSUPPORT_BITMAP_FORMAT;
            }
        }
    }
    if ((ret = AndroidBitmap_unlockPixels(env, bitmap)) < 0) {
        LOGI("AndroidBitmap_unlockPixels failed,error=%d", ret);
        return ret;
    }
    // 编码压缩图片
    ret = compressJPEG(tmpData, width, height, quality, outPath);
    free((void *) tmpData);
    return ret;
}

std::vector<uint8_t> readNextJPEGFrame(FILE *fp) {
    std::vector<uint8_t> buffer;
    bool inFrame = false;
    uint8_t prev = 0;

    while (!feof(fp)) {
        uint8_t curr = fgetc(fp);

        if (!inFrame) {
            if (prev == 0xFF && curr == 0xD8) {
                inFrame = true;
                buffer.push_back(prev);
                buffer.push_back(curr);
            }
        } else {
            buffer.push_back(curr);
            // 检测终止符
            if (prev == 0xFF && curr == 0xD9) {
                if (buffer.size() > 4096) {
                    inFrame = false;
                    prev = 0;
                    return buffer;
                }
            }
            // 跳过填充字节
            if (prev == 0xFF && curr == 0x00) {
                buffer.pop_back();  // 移除 0x00
                continue;
            }
        }
        prev = curr;  // 关键：每次循环更新 prev
    }
    return buffer;  // 返回不完整数据（可选处理）
}

// YCbCr到RGBA的转换函数（需要实现）
void convertYCbCrToRGBA(const uint8_t *src, uint8_t *dst, int width, int components) {
    // 实现YCbCr到RGBA的转换
    // 示例：简单的灰度转换
    for (int i = 0; i < width; i++) {
        uint8_t y = src[i * components];
        dst[i * 4 + 0] = y; // R
        dst[i * 4 + 1] = y; // G
        dst[i * 4 + 2] = y; // B
        dst[i * 4 + 3] = 255; // A
    }
}

void my_error_exit() {
    LOGI("my_error_exit");
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_huitao_jpegdemo_MainActivity_nativeDecodeMJPEG(JNIEnv *env, jobject thiz, jstring path,
                                                        jobject surface) {
    const char* jpegPath = env->GetStringUTFChars(path, 0);
    FILE* infile = fopen(jpegPath, "rb");

    // 初始化解码结构体
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);

    // 读取头信息并设置缩放参数（例如缩小到1/2）
    jpeg_read_header(&cinfo, TRUE);
    cinfo.scale_num = 1;
    cinfo.scale_denom = 2;
    jpeg_start_decompress(&cinfo);

    // 创建 Bitmap 对象
    jobject bitmap = nullptr;
    int width = cinfo.output_width;
    int height = cinfo.output_height;
    //AndroidBitmap_createBitmap(env, &bitmap, width, height, ANDROID_BITMAP_FORMAT_RGBA_8888);

    // 解码像素数据到缓冲区
    JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, cinfo.output_width * 4, 1);
    while (cinfo.output_scanline < cinfo.output_height) {
        jpeg_read_scanlines(&cinfo, buffer, 1);
        // 将 RGB 转换为 ARGB（根据实际需求调整）
        uint8_t* pixels;
        AndroidBitmap_lockPixels(env, bitmap, (void**)&pixels);
        // 处理像素数据...
        AndroidBitmap_unlockPixels(env, bitmap);
    }

    // 清理资源
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    env->ReleaseStringUTFChars(path, jpegPath);

    return bitmap;

}

